/*
 * @(#)MaintWorkflowSubmissionAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.workflow.web;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractMaintAction;
import com.dcivision.framework.web.WorkflowActionFormInterface;
import com.dcivision.user.bean.MtmUserGroupUserRole;
import com.dcivision.user.bean.MtmUserRecordUserGroup;
import com.dcivision.user.bean.MtmUserRecordUserRole;
import com.dcivision.user.bean.UserDelegation;
import com.dcivision.user.dao.MtmUserGroupUserRoleDAObject;
import com.dcivision.user.dao.MtmUserRecordUserGroupDAObject;
import com.dcivision.user.dao.MtmUserRecordUserRoleDAObject;
import com.dcivision.user.dao.UserDelegationDAObject;
import com.dcivision.workflow.WorkflowOperationConstant;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.WorkflowDocTrackingRecord;
import com.dcivision.workflow.bean.WorkflowGroup;
import com.dcivision.workflow.bean.WorkflowProgress;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.core.SystemWorkflowConstant;
import com.dcivision.workflow.core.WorkflowPermissionManager;
import com.dcivision.workflow.core.WorkflowProgressManager;
import com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject;
import com.dcivision.workflow.dao.WorkflowGroupDAObject;
import com.dcivision.workflow.dao.WorkflowProgressDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;

/**
  MaintWorkflowSubmissionAction.java

  This class is for maint workflow submission.

    @author          Angus Shiu
    @company         DCIVision Limited
    @creation date   11/12/2003
    @version         $Revision: 1.30 $
*/

public class MaintWorkflowSubmissionAction extends AbstractMaintAction implements com.dcivision.framework.web.WorkflowActionInterface {

  public static final String REVISION = "$Revision: 1.30 $";

  public static final String INITIAL_PROGRESS = "initialProgress";

  /** Creates a new instance of MaintWorkflowSubmissionAction */
  public MaintWorkflowSubmissionAction() {
    super();
  }

  public String getFunctionCode() {
    return(SystemFunctionConstant.WORKFLOW_SUBMISSION);
  }

  public String getMajorDAOClassName() {
    return("com.dcivision.workflow.dao.WorkflowRecordDAObject");
  }

  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException {
    AbstractActionForm maintForm = (AbstractActionForm)form;
    String opMode = (maintForm!=null) ? maintForm.getOpMode() : request.getParameter("opMode");    //maintForm.getOpMode();
    String navMode = (maintForm!=null) ? maintForm.getNavMode() : request.getParameter("navMode"); //maintForm.getNavMode();
    
    // Special handling for paper document, retreive the document ID according to the Reference No.
    MaintWorkflowRecordForm maintWFRecordForm = (MaintWorkflowRecordForm)form;
    
    //simon_add_start
    Connection conn = this.getConnection(request);
    SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
    //king.guo-add-start
    String right=this.getSubmissionRight(request, response, sessionContainer, conn);
    if (!Utility.isEmpty(right) && right.indexOf(WorkflowPermissionManager.EXECUTE_PERMISSION) >= 0) {
      request.setAttribute("ALLOW_EXECUTE", new Boolean(true));
    } else {
    	ActionError error=new ActionError("common.label.no_access_right");
    	ActionErrors errors=new ActionErrors();
    	errors.add(null, error);
    	this.saveErrors(request, errors);
    	request.setAttribute("ALLOW_EXECUTE", new Boolean(false));
    }
    //king.guo-add-end
    String workflowGroupID=maintWFRecordForm.getWorkflowGroupID();
    WorkflowGroupDAObject wfGroupDAO = new WorkflowGroupDAObject(sessionContainer, conn);
    WorkflowGroup wfGroup = (WorkflowGroup) wfGroupDAO.getObjectByID(new Integer(workflowGroupID));
    request.setAttribute("workflowGroup", wfGroup);
    //simon_add_end
    
    if(!Utility.isEmpty(maintWFRecordForm.getDocumentReferenceNo())){
      request.setAttribute("documentReferenceNo",maintWFRecordForm.getDocumentReferenceNo());
      if ( SystemWorkflowConstant.DMS_PAPER_DOCUMENT.equals(maintWFRecordForm.getWorkflowCategoryID()) ) {
        com.dcivision.dms.dao.DmsDocumentDAObject dmsDocumentDAO = new com.dcivision.dms.dao.DmsDocumentDAObject(this.getSessionContainer(request), this.getConnection(request));
        com.dcivision.dms.bean.DmsDocument dmsDoc  = (com.dcivision.dms.bean.DmsDocument)dmsDocumentDAO.getObjectByReferenceNo(GlobalConstant.RECORD_STATUS_ACTIVE, maintWFRecordForm.getDocumentReferenceNo().trim(), com.dcivision.dms.bean.DmsDocument.PAPER_DOC_TYPE);
        if (dmsDoc == null) {
          addError(request, ErrorConstant.DB_RECORD_NOT_FOUND_ERROR);
          return mapping.findForward(GlobalConstant.NAV_MODE_NEW);
        } else {
          // check permission, the submitted user should have read permission on the paper document
          maintWFRecordForm.setDocumentID(dmsDoc.getID().toString());
          if ( !this.getSessionContainer(request).getPermissionManager().hasAccessRight ( GlobalConstant.OBJECT_TYPE_DOCUMENT, Integer.valueOf(maintWFRecordForm.getDocumentID()), "R" ) ) {
            addError ( request, ErrorConstant.COMMON_UNAUTHORIZED_ACCESS );
            return mapping.findForward(GlobalConstant.NAV_MODE_NEW);
          } else {
            //  check if this paper document is already started by some progress
            //  1. Select all progress (by Track ID) related to this paper document
            //  2. If there is a pending/post-process status, assume the whole process is not finished

            WorkflowProgressDAObject wpDAO = new WorkflowProgressDAObject ( this.getSessionContainer(request), this.getConnection(request));
            ListWorkflowDocTrackingForm docTrackForm = new ListWorkflowDocTrackingForm();
            docTrackForm.setDocReferenceNumber(maintWFRecordForm.getDocumentReferenceNo());
            List docTrackList = wpDAO.getListDocTracking(docTrackForm);
            for ( int i = 0; i<docTrackList.size(); i++ ) {
              WorkflowDocTrackingRecord docTrackRecord = (WorkflowDocTrackingRecord) docTrackList.get(i);
              List wpList = docTrackRecord.getWorkflowProgressList();
              for ( int j=0;j<wpList.size();j++) {
                WorkflowProgress wp = (WorkflowProgress)wpList.get(j);
                if ( WorkflowProgress.STATUS_PENDING.equals(wp.getStatus()) ) {
                  //  Assume the whole process of sending paper document is not finished
                  addError ( request, ErrorConstant.WORKFLOW_PAPER_DOCUMENT_ALREADY_STARTED );
                  return mapping.findForward(GlobalConstant.NAV_MODE_NEW);
                }
              }
            }
          }
        }
      }
    }
    if(request.getParameter("timelice")!=null && request.getParameter("timelice")!=""){
        if(request.getSession().getAttribute("timelice")!=null && request.getSession().getAttribute("timelice")!=""){
          if((request.getParameter("timelice")).equals(request.getSession().getAttribute("timelice"))){
        	 if(maintForm.getOpMode()!=null){
        	   maintForm.setOpMode(null);
             }
             if(maintForm.getNavMode()!=null && maintForm.getNavMode()!=""){
	            if(!GlobalConstant.NAV_MODE_VIEW.equals(maintForm.getNavMode())){			    
	    	      maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
	            }
             }else{
	            maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
             }
            return super.execute(mapping,form,request,response);
          }
          else{
        	  request.getSession().setAttribute("timelice", request.getParameter("timelice"));
          }
        }else{
        	request.getSession().setAttribute("timelice", request.getParameter("timelice"));
        }
    if (GlobalConstant.OP_MODE_UPDATE.equals(opMode)) {
      //Set the function code for current action.
      ActionForward forward = this.retrieveFunctionCode(request, response, mapping);
      if (forward!=null) {
        return forward;
      }
      
      try {
        this.updateRecord(mapping, maintForm, request, response);
        this.handleWorkflowRoutine(mapping, maintForm, request, response, opMode, navMode);
        this.commit(request);
        addMessage(request, MESSAGE_RECORD_INSERT);
      } catch (ApplicationException appEx) {
        this.rollback(request);
        handleApplicationException(request, appEx);
      }
      if (isError(request)) {
        maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
        return mapping.findForward(GlobalConstant.NAV_MODE_NEW);
      } else {
        //===== For Handle The Second Step IS Dynamic Assign Owner Begin =======
        HashMap tmp = (HashMap) request.getAttribute("assignStepMap");
        if (tmp!=null && !tmp.isEmpty()) {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
          request.setAttribute("returnUrl","workflow/ListWorkflowSubmission.do");
          request.setAttribute("workflowCategoryID",request.getParameter("workflowCategoryID"));
          request.setAttribute("oldStatus",WorkflowProgress.STATUS_SUBMIT);
          return mapping.findForward(WorkflowOperationConstant.WORKFLOW_ASSIGN_USER);
        //===== For Handle The Second Step IS Dynamic Assign Owner End   =======
        } else {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
          return mapping.findForward(GlobalConstant.NAV_MODE_VIEW);
        }
      }

    }
    }
    return super.execute(mapping,form,request,response);
  }

  public void updateRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    SessionContainer sessionCon = this.getSessionContainer(request);

    WorkflowProgressManager progressManager = new WorkflowProgressManager(sessionCon, this.getConnection(request));
    WorkflowProgress progress = (WorkflowProgress) progressManager.startWorkflowTrack(form);
    request.setAttribute("assignStepMap",progressManager.getAssignStepMap());
    request.setAttribute(MaintWorkflowSubmissionAction.INITIAL_PROGRESS, progress);
    //request.getSession().setAttribute(MaintWorkflowSubmissionAction.INITIAL_PROGRESS, progress);//sliever.hu.add  //simon_del
    java.sql.Connection conn = this.getConnection(request);
    com.dcivision.customize.workflow.CustomizationForAction customization = new com.dcivision.customize.workflow.CustomizationForAction();
    customization.workflowSubmissionCustomization(sessionCon, conn, request, (MaintWorkflowRecordForm)form, progress);
    conn = null;
  }

  public void executeWorkflowRoutine(ActionMapping mapping, WorkflowActionFormInterface form, HttpServletRequest request, HttpServletResponse response, String opMode, String navMode) throws ApplicationException {
    log.info("########## MaintFormSubmissionAction Workflow Routine Begin ##########");
    String workflowRecordID = request.getParameter("workflowRecordID");
    String workflowComment = request.getParameter("workflowComment");
    log.info("########## MaintFormSubmissionAction Workflow Routine End   ##########");
  }

  public void handleWorkflowRoutine(ActionMapping mapping,
                                    AbstractActionForm maintForm,
                                    HttpServletRequest request,
                                    HttpServletResponse response,
                                    String opMode,
                                    String navMode)
    throws ApplicationException {
    super.handleWorkflowRoutine(mapping, maintForm, request, response, opMode, navMode);
  }
  
//  20060317_king_add_start  //
  private String getSubmissionRight(HttpServletRequest request, HttpServletResponse response,SessionContainer sessionContainer,Connection conn) throws ApplicationException {
    
	  String workflowID = request.getParameter("ID");	  	  
	  Integer userID = sessionContainer.getUserRecordID();
	  String right = "";
	  // right=checkSubmissionRight(workflow_id,user_id,request,response,sessionContainer,conn);
    right = getSubmissionPermission(Integer.valueOf(workflowID), userID, request);
	  if(!Utility.isEmpty(right)){
		  return right;		  
	  }
    
	  //check by delegation	  	  
		UserDelegationDAObject delegationDAO=new UserDelegationDAObject(sessionContainer,conn);
		List delegateList = delegationDAO.getListDelegatedToUser(userID);
		Iterator delegateIt=delegateList.iterator();
		while(delegateIt.hasNext()){
			UserDelegation tmpUserDelegation=(UserDelegation)delegateIt.next();
			Integer sourceID=tmpUserDelegation.getSourceUserID();
			// right=checkSubmissionRight(workflow_id,String.valueOf(sourceID),request,response,sessionContainer,conn);
			right = getSubmissionPermission(Integer.valueOf(workflowID), sourceID, request);
			if(!Utility.isEmpty(right)){
				return right;
			}
		}
    
	  return right;
  }
  
  private String getSubmissionPermission(Integer workflowID, Integer userID, HttpServletRequest request) throws ApplicationException {
    WorkflowStepDAObject wfStepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStep submitStep =(WorkflowStep) wfStepDAO.getSubmitStepByWorkflowRecordID(workflowID);             
    Integer submitStepID = submitStep.getID();
    
    WorkflowPermissionManager wfPermManager = new WorkflowPermissionManager(this.getSessionContainer(request), this.getConnection(request));
    
    String permissionValue = wfPermManager.getUserPermission4SpecialTask(submitStepID, null, userID);
    
    return (permissionValue);
  }
  
  /**
   * @deprecated
   * @param workflowID
   * @param userID
   * @param request
   * @param response
   * @param sessionContainer
   * @param conn
   * @return
   */
  private String checkSubmissionRight(String workflowID,String userID,HttpServletRequest request,HttpServletResponse response,SessionContainer sessionContainer,Connection conn){ 
	  String right="R";	  
	  String workflow_id=workflowID;	  	  
	  String user_id=userID;	  
	  try {		  
		  WorkflowStepDAObject wfStepDAO =new WorkflowStepDAObject(sessionContainer,conn);
		  WorkflowStep tmpWorkflowStep =(WorkflowStep)wfStepDAO.getSubmitStepByWorkflowRecordID(Integer.valueOf(workflow_id));		  		   
		  Integer wf_id=tmpWorkflowStep.getID();			  
		  MtmWorkflowStepUserActorDAObject wfUserActorDAO=new MtmWorkflowStepUserActorDAObject(sessionContainer,conn);		  
		  //check by everyone	  
		  List listEveryone=wfUserActorDAO.getListByWorkflowStepIDAndActorType(wf_id,MtmWorkflowStepUserActor.ACTOR_TYPE_EVERYONE);
		  Iterator itEveryone=listEveryone.iterator();		  
		  while(itEveryone.hasNext()){
			  MtmWorkflowStepUserActor tmpMtmWorkflowStepUserActor =(MtmWorkflowStepUserActor)itEveryone.next();			  			  			  			
				  if(tmpMtmWorkflowStepUserActor.getPermission().equals("RW")){					  
					  right="RW";
					  return right;
				  }			  
		  } 
		  //check by user	  
		  List listUser=wfUserActorDAO.getListByWorkflowStepIDAndActorType(wf_id,GlobalConstant.SUBJECT_TYPE_USER);
		  Iterator it=listUser.iterator();		  
		  while(it.hasNext()){
			  MtmWorkflowStepUserActor tmpMtmWorkflowStepUserActor =(MtmWorkflowStepUserActor)it.next();
			  String tmpUser_id=String.valueOf(tmpMtmWorkflowStepUserActor.getActorID());			  
			  if(tmpUser_id.equals(user_id)){				
				  if(tmpMtmWorkflowStepUserActor.getPermission().equals("RW")){					  
					  right="RW";
					  return right;
				  }
			  }			  
		  } 
		  //check by group
		  MtmUserRecordUserGroupDAObject userGroupDAO=new MtmUserRecordUserGroupDAObject(sessionContainer,conn);
		  List listGroup=userGroupDAO.getListByUserRecordID(Integer.valueOf(user_id));
		  Iterator itGroup=listGroup.iterator();
		  while(itGroup.hasNext()){
			  MtmUserRecordUserGroup tmpMtmUserRecordUserGroup=(MtmUserRecordUserGroup)itGroup.next();
			  String groupID=String.valueOf(tmpMtmUserRecordUserGroup.getUserGroupID());
			  List listWFByGroup=wfUserActorDAO.getListByWorkflowStepIDAndActorType(wf_id,GlobalConstant.SUBJECT_TYPE_GROUP);
			  Iterator itWFByGroup=listWFByGroup.iterator();
			  while(itWFByGroup.hasNext()){
				  MtmWorkflowStepUserActor tmpMtmWorkflowStepUserActor =(MtmWorkflowStepUserActor)itWFByGroup.next();
				  String tmpGroupID=String.valueOf(tmpMtmWorkflowStepUserActor.getActorID());
				  if(tmpGroupID.equals(groupID)){
					  if(tmpMtmWorkflowStepUserActor.getPermission().equals("RW")){
						  right="RW";
						  return right;
					  }
				  }
			  }
		  }
		  //check by role
		  MtmUserRecordUserRoleDAObject userRoleDAO=new MtmUserRecordUserRoleDAObject(sessionContainer,conn);
		  List listRole=userRoleDAO.getListByUserRecordID(Integer.valueOf(user_id));
		  List roleListID=new ArrayList();
		  Iterator itRole=listRole.iterator();
		  while(itRole.hasNext()){
			  MtmUserRecordUserRole tmpMtmUserRecordUserRole = (MtmUserRecordUserRole)itRole.next();
			  String roleID=String.valueOf(tmpMtmUserRecordUserRole.getUserRoleID());
			  roleListID.add(Integer.valueOf(roleID));
			  List listWFByRole=wfUserActorDAO.getListByWorkflowStepIDAndActorType(wf_id,GlobalConstant.SUBJECT_TYPE_ROLE);
			  Iterator itWFByRole=listWFByRole.iterator();
			  while(itWFByRole.hasNext()){
				  MtmWorkflowStepUserActor tmpMtmWorkflowStepUserActor =(MtmWorkflowStepUserActor)itWFByRole.next();
				  String tmpRoleID=String.valueOf(tmpMtmWorkflowStepUserActor.getActorID());
				  if(tmpRoleID.equals(roleID)){
					  if(tmpMtmWorkflowStepUserActor.getPermission().equals("RW")){					  
						  right="RW";
						  return right;
					  }					  
				  }
			  }
		  }
		  //check by group user role
		  MtmUserGroupUserRoleDAObject userGroupRole=new MtmUserGroupUserRoleDAObject(sessionContainer,conn);		  
		  List groupUserRoleList=userGroupRole.getListByUserRoleAry(roleListID);		  
		  Iterator itGroupUserRole=groupUserRoleList.iterator();
		  while(itGroupUserRole.hasNext()){
			  MtmUserGroupUserRole tmpMtmUserGroupUserRole=(MtmUserGroupUserRole)itGroupUserRole.next();
			  String groupID=String.valueOf(tmpMtmUserGroupUserRole.getUserRoleID());
			  List listWFByGroup=wfUserActorDAO.getListByWorkflowStepIDAndActorType(wf_id,GlobalConstant.SUBJECT_TYPE_ROLE);
			  Iterator itWFByGroup=listWFByGroup.iterator();
			  while(itWFByGroup.hasNext()){
				  MtmWorkflowStepUserActor tmpMtmWorkflowStepUserActor =(MtmWorkflowStepUserActor)itWFByGroup.next();
				  String tmpGroupID=String.valueOf(tmpMtmWorkflowStepUserActor.getActorID());
				  if(tmpGroupID.equals(groupID)){
					  if(tmpMtmWorkflowStepUserActor.getPermission().equals("RW")){
						  right="RW";
						  return right;
					  }
				  }
			  }
		  }
  }catch (ApplicationException e) {
	  	log.error(e,e);
		return right;
	}	
  return right;
}
//  20060317_king_add_end  //
}